package com.punai.assetlibrary.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.punai.assetlibrary.entiry.dtos.ZjfzckDto;
import com.punai.assetlibrary.service.ZJFZckService;
import com.punai.common.utils.NumberUtil;
import com.punai.dataclean.constants.CostDataConstanta;
import com.punai.evaluationSystem.costDataEvalute.domain.EvaluationCbInfo;
import com.punai.evaluationSystem.costDataEvalute.domain.EvaluationDataPrice;
import com.punai.evaluationSystem.costDataEvalute.domain.EvaluationResults;
import com.punai.evaluationSystem.costDataEvalute.mapper.EvaluationCbInfoMapper;
import com.punai.evaluationSystem.costDataEvalute.mapper.EvaluationDataPriceMapper;
import com.punai.evaluationSystem.costDataEvalute.mapper.EvaluationResultsMapper;
import com.punai.prodatalibrary.domain.LibProjectInfo;
import com.punai.prodatalibrary.mapper.LibProjectInfoMapper;
import com.punai.standard.domain.*;
import com.punai.standard.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ZJFZckServiceImpl implements ZJFZckService {

    @Autowired
    private EvaluationDataPriceMapper evaluationDataPriceMapper;

    @Autowired
    private EvaluationResultsMapper evaluationResultsMapper;

    @Autowired
    private EvaluationCbInfoMapper evaluationCbInfoMapper;

    @Autowired
    private StaGxChapterMapper staGxChapterMapper;

    @Autowired
    private StaGxFeeMapper staGxFeeMapper;

    @Autowired
    private StaFbFeeMapper staFbFeeMapper;
    @Autowired
    private StaClFeeMapper staClFeeMapper;
    @Autowired
    private StaJxFeeMapper staJxFeeMapper;

    @Autowired
    private StaClChapterMapper staClChapterMapper;


    @Autowired
    private LibProjectInfoMapper libProjectInfoMapper;

    @Autowired
    private StaJxChapterMapper staJxChapterMapper;

    @Autowired
    private StaFbChapterMapper staFbChapterMapper;



    private static final String GX_ROOT_ID = "GX_ROOT_ID";
    private static final String CB_ROOT_ID = "CB_ROOT_ID";

    @Override
    public List<EvaluationDataPrice> initTableData(ZjfzckDto zjfzckDto) {
        String tabName = zjfzckDto.getTabName();

        Set<String> codes = new HashSet<>();
        if (CostDataConstanta.Tabs.FB_0.getCode().equals(tabName)) {
            if (StrUtil.equals(GX_ROOT_ID, zjfzckDto.getGxCbType())){
                List<String> chapterIds = new ArrayList<>();
                if (StrUtil.isNotEmpty(zjfzckDto.getCategoryId())) {
                    chapterIds.add(zjfzckDto.getCategoryId());
                    List<StaGxChapter> childByPid = staGxChapterMapper.selectList(Wrappers.<StaGxChapter>lambdaQuery()
                            .eq(StaGxChapter::getVersionId, zjfzckDto.getVersionId())
                            .apply(StrUtil.isNotEmpty(zjfzckDto.getCategoryId()),"find_in_set('"+zjfzckDto.getCategoryId()+"',pids)"));
                    if (CollUtil.isNotEmpty(childByPid)) {
                        chapterIds.addAll(childByPid.stream().map(StaGxChapter::getId).collect(Collectors.toList()));
                    }
                }
                List<StaGxFee> staGxFees = staGxFeeMapper.selectList(
                        Wrappers.<StaGxFee>lambdaQuery()
                                .in(chapterIds.size() > 0, StaGxFee::getChapterId, chapterIds)
                                .eq(StaGxFee::getVersionId, zjfzckDto.getVersionId())
                                .orderBy(true, true, StaGxFee::getCode)
                                .orderBy(true, true, StaGxFee::getOrderNum)
                );
                //获取所有费用项编码
                codes = staGxFees.stream().map(StaGxFee::getCode).collect(Collectors.toSet());
                zjfzckDto.setCodes(codes);
            } else if (StrUtil.equals(CB_ROOT_ID, zjfzckDto.getGxCbType())){
                List<String> chapterIds = new ArrayList<>();
                if (StrUtil.isNotEmpty(zjfzckDto.getCategoryId())) {
                    chapterIds.add(zjfzckDto.getCategoryId());
                    List<StaFbChapter> childByPid = staFbChapterMapper.selectList(Wrappers.<StaFbChapter>lambdaQuery()
                            .eq(StaFbChapter::getVersionId, zjfzckDto.getVersionId())
                            .apply(StrUtil.isNotEmpty(zjfzckDto.getCategoryId()), "find_in_set('" + zjfzckDto.getCategoryId() + "',pids)"));
                    if (CollUtil.isNotEmpty(childByPid)) {
                        chapterIds.addAll(childByPid.stream().map(StaFbChapter::getId).collect(Collectors.toList()));
                    }
                }
                List<StaFbFee> staFbFees = staFbFeeMapper.selectList(
                        Wrappers.<StaFbFee>lambdaQuery()
                                .in(chapterIds.size() > 0, StaFbFee::getChapterId, chapterIds)
                                .eq(StaFbFee::getVersionId, zjfzckDto.getVersionId())
                                .orderBy(true, true, StaFbFee::getCode)
                                .orderBy(true, true, StaFbFee::getOrderNum)
                );

                codes = staFbFees.stream().map(StaFbFee::getCode).collect(Collectors.toSet());
                zjfzckDto.setCodes(codes);
            }
            if(codes.size() == 0) return Collections.emptyList();
        } else if (CostDataConstanta.Tabs.CL_1.getCode().equals(tabName)) {
            List<String> chapterIds = new ArrayList<>();
            if (StrUtil.isNotEmpty(zjfzckDto.getCategoryId())) {
                chapterIds.add(zjfzckDto.getCategoryId());
                List<StaClChapter> childByPid = staClChapterMapper.selectList(Wrappers.<StaClChapter>lambdaQuery()
                        .eq(StaClChapter::getVersionId, zjfzckDto.getVersionId())
                        .apply(StrUtil.isNotEmpty(zjfzckDto.getCategoryId()), "find_in_set('" + zjfzckDto.getCategoryId() + "',pids)"));
                if (CollUtil.isNotEmpty(chapterIds)) {
                    chapterIds.addAll(childByPid.stream().map(StaClChapter::getId).collect(Collectors.toList()));
                }
            }
            List<StaClFee> staFbFees = staClFeeMapper.selectList(
                    Wrappers.<StaClFee>lambdaQuery()
                            .in(chapterIds.size() > 0, StaClFee::getChapterId, chapterIds)
                            .eq(StaClFee::getVersionId, zjfzckDto.getVersionId())
                            .orderBy(true, true, StaClFee::getCode)
                            .orderBy(true, true, StaClFee::getOrderNum)
            );

            codes = staFbFees.stream().map(StaClFee::getCode).collect(Collectors.toSet());
            zjfzckDto.setCodes(codes);
        } else if (CostDataConstanta.Tabs.JX_2.getCode().equals(tabName)) {
            List<String> chapterIds = new ArrayList<>();
            if (StrUtil.isNotEmpty(zjfzckDto.getCategoryId())) {
                chapterIds.add(zjfzckDto.getCategoryId());
                List<StaJxChapter> childByPid = staJxChapterMapper.selectList(Wrappers.<StaJxChapter>lambdaQuery()
                        .eq(StaJxChapter::getVersionId, zjfzckDto.getVersionId())
                        .apply(StrUtil.isNotEmpty(zjfzckDto.getCategoryId()), "find_in_set('" + zjfzckDto.getCategoryId() + "',pids)"));
                if (CollUtil.isNotEmpty(chapterIds)) {
                    chapterIds.addAll(childByPid.stream().map(StaJxChapter::getId).collect(Collectors.toList()));
                }
            }
            List<StaJxFee> staFbFees = staJxFeeMapper.selectList(
                    Wrappers.<StaJxFee>lambdaQuery()
                            .in(chapterIds.size() > 0, StaJxFee::getChapterId, chapterIds)
                            .eq(StaJxFee::getVersionId, zjfzckDto.getVersionId())
                            .orderBy(true, true, StaJxFee::getCode)
                            .orderBy(true, true, StaJxFee::getOrderNum)
            );
            codes = staFbFees.stream().map(StaJxFee::getCode).collect(Collectors.toSet());
            zjfzckDto.setCodes(codes);
        } else if (CostDataConstanta.Tabs.JJ_3.getCode().equals(tabName)) {

        }

        List<EvaluationDataPrice> allBySqlQuery = evaluationDataPriceMapper.findAllDataByMap(BeanUtil.beanToMap(zjfzckDto));

        Map<String, List<EvaluationDataPrice>> map = allBySqlQuery.stream().collect(Collectors.groupingBy(EvaluationDataPrice::getCode));

        List<EvaluationDataPrice> result = new ArrayList<>();

        if (CollUtil.isNotEmpty(map)) {
            for (Map.Entry<String, List<EvaluationDataPrice>> listEntry : map.entrySet()) {
                List<EvaluationDataPrice> value = listEntry.getValue();
                List<String> ids = value.stream().map(EvaluationDataPrice::getId).collect(Collectors.toList());
                List<EvaluationCbInfo> evaluateInfoList = evaluationCbInfoMapper.selectList(Wrappers.<EvaluationCbInfo>lambdaQuery().in(EvaluationCbInfo::getPid, ids));
                Map<BigDecimal, List<EvaluationCbInfo>> priceMap = evaluateInfoList.stream().filter(v -> v.getPrice() != null).collect(Collectors.groupingBy(EvaluationCbInfo::getPrice, Collectors.toList()));
                if (CollUtil.isNotEmpty(value) && CollUtil.isNotEmpty(evaluateInfoList)){
                    value.get(0).setCountbtjgsl(String.valueOf(priceMap.size()));
                    result.add(value.get(0));
                }
            }
        }

        return result;
    }

    @Override
    public EvaluationResults findByPid(String pid) {
        return evaluationResultsMapper.selectOne(Wrappers.<EvaluationResults>lambdaQuery().eq(EvaluationResults::getId, pid));
    }

    @Override
    public List<EvaluationCbInfo> findAllEvaluationInfo(Map<String, List<EvaluationDataPrice>> map) {
        List<EvaluationCbInfo> res = new ArrayList<>();
        for (Map.Entry<String, List<EvaluationDataPrice>> entry : map.entrySet()) {
            String pjType = "";
            if (CollUtil.isNotEmpty(entry.getValue())){
                EvaluationResults results = findByPid(entry.getValue().get(0).getPid()) ;
                pjType = results.getEvaluateType();
            }
            List<String> ids = entry.getValue().stream().map(EvaluationDataPrice::getId).collect(Collectors.toList());
            List<EvaluationCbInfo> evaluateInfoList = evaluationCbInfoMapper.selectList(Wrappers.<EvaluationCbInfo>lambdaQuery().in(EvaluationCbInfo::getPid, ids));
            if (CollUtil.isNotEmpty(evaluateInfoList)){
                for (EvaluationCbInfo evaluateInfo : evaluateInfoList) {
                    evaluateInfo.setPjjgsj(entry.getKey());
                    LibProjectInfo basicInfo = libProjectInfoMapper.selectOne(Wrappers.<LibProjectInfo>lambdaQuery()
                            .eq(LibProjectInfo::getProId, evaluateInfo.getProid()));
                    evaluateInfo.setProjectDept(basicInfo.getProjectDept());
                    evaluateInfo.setAddress(basicInfo.getProvince() + basicInfo.getCity() + basicInfo.getRegion());
                    evaluateInfo.setPjType(pjType);
                    res.add(evaluateInfo);
                }
            }
        }
        return res;
    }

    @Override
    public List<EvaluationDataPrice> findAllEvaluationDataPrice(ZjfzckDto zjfzckDto) {
        return evaluationDataPriceMapper.findAllEvaluationDataPrice(BeanUtil.beanToMap(zjfzckDto));
    }

    @Override
    public Map<String, String> findByCode(ZjfzckDto zjfzckDto) {
        List<EvaluationResults> list = evaluationResultsMapper.findAllByCode(BeanUtil.beanToMap(zjfzckDto));

        list = list.stream().sorted(Comparator.comparing(EvaluationResults::getEvaluateType)).collect(Collectors.toList());
        Map<String,String> map = new HashMap<>();
        if (CollUtil.isNotEmpty(list)) {
            for (EvaluationResults results : list) {
                map.put(results.getPjjgsj(),results.getEvaluateType());
            }
        }
        Map<String, String> sortMap = sortMap(map);
        return sortMap;
    }


    public Map<String, String> sortMap(Map<String, String> map) {
        //利用Map的entrySet方法，转化为list进行排序
        List<Map.Entry<String, String>> entryList = new ArrayList<>(map.entrySet());
        //利用Collections的sort方法对list排序
        Collections.sort(entryList, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                //正序排列，倒序反过来
                return NumberUtil.createInteger(o1.getValue()) - NumberUtil.createInteger(o2.getValue());
            }
        });
        //遍历排序好的list，一定要放进LinkedHashMap，因为只有LinkedHashMap是根据插入顺序进行存储
        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<String, String>();
        for (Map.Entry<String,String> e : entryList) {
            linkedHashMap.put(e.getKey().replaceAll("\\.","-"),e.getValue());
        }
        return linkedHashMap;
    }


    @Override
    public List<EvaluationResults> getQc(ZjfzckDto zjfzckDto) {
        return evaluationResultsMapper.findAllByCode(BeanUtil.beanToMap(zjfzckDto));
    }
}
